from fastapi import Depends
import os
import redis
import pickle
from typing import Any, Optional
from datetime import datetime, timedelta

from scorpio.core.common import (
    SESSION_DATA_FILE,
    get_config,
    get_logger    
)
logger = get_logger(__name__)

def check_config() -> bool:
    config_path=os.getenv('SCORPIO_CONF') or os.getcwd()+'/scorpio_config.json' or None
    if config_path:
        if not os.path.isfile(config_path):
            return True
        else:
            return False
    else:
        return False
    
def get_dependencies() -> list[Depends]:
    result = []
    result.append(Depends(get_config))
    return result


# 存储抽象层
class SessionStore:
    def __init__(self):
        self.store_type = self.detect_store_type()
        if self.store_type == "redis":
            self.redis_conn = redis.Redis(
                host=os.getenv("REDIS_HOST", "localhost"),
                port=int(os.getenv("REDIS_PORT", 6379)),
                db=int(os.getenv("REDIS_DB", 0)),
                decode_responses=False
            )
        elif self.store_type == "memory":
            self.memory_store = {}
            self.load_from_disk()
    
    def detect_store_type(self) -> str:
        """根据环境变量和Redis可用性决定存储类型"""
        enable_redis=os.getenv("REDIS_ENABELD", None)
        # 测试Redis连接
        if enable_redis:
            return "redis"
        else:
            return "memory"
    
    def set(self, key: str, value: Any, ttl: Optional[int] = None) -> bool:
        """存储数据"""
        if self.store_type == "redis":
            try:
                serialized = pickle.dumps(value)
                if ttl:
                    return self.redis_conn.setex(key, ttl, serialized)
                return self.redis_conn.set(key, serialized)
            except redis.RedisError as e:
                logger.error(f"Redis error: {e}")
                raise
        else:  # memory
            self.memory_store[key] = (value, datetime.now() + timedelta(seconds=ttl)) if ttl else (value, None)
            self.persist_to_disk()
            return True
    
    def get(self, key: str) -> Any:
        """获取数据"""
        if self.store_type == "redis":
            try:
                serialized = self.redis_conn.get(key)
                return pickle.loads(serialized) if serialized else None
            except redis.RedisError as e:
                logger.error(f"Redis error: {e}")
                return None
        else:  # memory
            if key not in self.memory_store:
                return None
                
            data, expiry = self.memory_store[key]
            # 检查是否过期
            if expiry and datetime.now() > expiry:
                del self.memory_store[key]
                self.persist_to_disk()
                return None
                
            return data
    
    def delete(self, key: str) -> bool:
        """删除数据"""
        if self.store_type == "redis":
            try:
                return self.redis_conn.delete(key) > 0 # type: ignore
            except redis.RedisError as e:
                logger.error(f"Redis error: {e}")
                return False
        else:  # memory
            if key in self.memory_store:
                del self.memory_store[key]
                self.persist_to_disk()
                return True
            return False
    
    def exists(self, key: str) -> bool:
        """检查键是否存在"""
        if self.store_type == "redis":
            try:
                return self.redis_conn.exists(key) > 0 # type: ignore
            except redis.RedisError as e:
                logger.error(f"Redis error: {e}")
                return False
        else:  # memory
            # 检查过期
            if key in self.memory_store:
                _, expiry = self.memory_store[key]
                if expiry and datetime.now() > expiry:
                    del self.memory_store[key]
                    self.persist_to_disk()
                    return False
                return True
            return False
    
    def persist_to_disk(self) -> None:
        """将内存存储持久化到磁盘"""
        if self.store_type != "memory":
            return
            
        try:
            # 使用pickle序列化
            with open(SESSION_DATA_FILE, "wb") as f:
                pickle.dump(self.memory_store, f)
        except Exception as e:
            logger.error(f"Persist to disk failed: {e}")
    
    def load_from_disk(self) -> None:
        """从磁盘加载持久化的会话数据"""
        if self.store_type != "memory":
            return
            
        try:
            if os.path.exists(SESSION_DATA_FILE):
                with open(SESSION_DATA_FILE, "rb") as f:
                    self.memory_store = pickle.load(f)
                logger.info(f"Loaded {len(self.memory_store)} sessions from disk")
        except Exception as e:
            logger.error(f"Load from disk failed: {e}")
            self.memory_store = {}
